#ifndef __YOLOV3_GPU_DETECTOR_H
#define __YOLOV3_GPU_DETECTOR_H


#include <unordered_map>
#include <unordered_set>


#include <opencv2/dnn.hpp>

class yoloV3GPUDetector 
  {
  public:
    yoloV3GPUDetector(const std::string& modelpath);
    ~yoloV3GPUDetector();

    void setParams(float aConfidenceThres,                           // Confidence threshold
                            std::unordered_set<std::string> aTargetClassname, // Classes need to be detected
                            std::string aModelFilePath,                       // Model file path
                            size_t aWidth,                                    // Block width to DNN
                            size_t aHeight);


    bool inference(cv::Mat &pFrame,
                      std::vector<cv::Rect2d> &pRoi,
                      std::vector<std::string> &pName,
                      std::vector<float> &pConf);
    int *runofftiny(cv::Mat &pFrame,
                  float _confidenceThreshold,
                  const std::vector<cv::Mat> &pOut,
                  cv::dnn::Net &pNet,
                  std::vector<cv::Rect2d> &pRoi,
                  std::vector<std::string> &pName,
                  std::vector<float> &pConf,
                  bool &pDetected);

    int cnt;
    double time_sum;
    double time_mean;
    float _confidenceThreshold=0.01;

  private:
    void drawPred(int aClassId, float aConf, int aLeft, int aTop, int aRight, int aBottom, cv::Mat &pFrame);
    std::vector<cv::String> getOutputsNames(const cv::dnn::Net &pNet);

    std::unordered_set<std::string> _targetName;
    cv::dnn::Net _dnnNet;
    std::vector<std::string> _classNames;
    std::string model_id_;
    size_t _inWidth, _inHeight;
    float _inScaleFactor, _meanVal;
    const std::string _kWinName = "YoloV3 object detection";
  };

  void cakkbacktiny(int, void *userdata);

#endif
